package com.ww.jmh;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Scope.Thread：线程私有
 * 1.规则：每个工作线程拥有独立的状态对象实例，即使类型相同，不同线程的实例也不共享
 * 2.Setup/TearDown：由每个线程自己执行一次（每个线程仅一次），其他线程无法访问
 * 3.适用场景：测试“线程私有资源”的性能（如ThreadLocal、线程私有缓存），或避免线程安全问题（如非线程安全的HashMap）
 */
@State(Scope.Thread)
public class ThreadScopeDemo {
    // 线程私有的HashMap（非线程安全）
    private Map<String, Integer> threadLocalMap;

    @Setup(Level.Trial)
    public void setup() {
        threadLocalMap = new java.util.HashMap<>();
        System.out.println("Thread Setup：初始化线程私有HashMap（线程：" + Thread.currentThread().getName() + "）");
    }

    @TearDown(Level.Trial)
    public void tearDown() {
        threadLocalMap.clear();
        System.out.println("Thread TearDown：清空线程私有HashMap（线程：" + Thread.currentThread().getName() + "）");
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    public void testThreadLocalMapPut() {
        threadLocalMap.put("key", (int) System.currentTimeMillis() % 1000);
    }

    public static void main(String[] args) throws RunnerException {
        Options opts = new OptionsBuilder()
                .include(ThreadScopeDemo.class.getSimpleName())
                .forks(1)
                .threads(4)
                .warmupIterations(2)
                .measurementIterations(3)
                .build();
        new Runner(opts).run();
    }
}
